var TICKET_URL = 'https://kyfw.12306.cn/otn/leftTicket/query'

var seatsKey = {
    'O':  '二等座',
    '1':  '硬座',
    'M':  '一等座',
    'F':  '动卧',
    '3':  '硬卧',
    '4':  '软卧',
    '6':  '高级软卧',
    '9':  '商务座',
    'W':  '无座',

}

var globalConfig = {
    timeout: 500, // 超时毫秒 ms
    waitTime: 0.2, // 单位秒 s
    submitFailed: false,
    submitWaitTime: 30, // 秒
    resubmit: 0,    // 重抢票新提交数
    maxResubmit: 3, // 限制抢票最大重新提交数
    // seat: '4',   // O, 3, 4
    // data: '2024-01-26',
    // trainNo: 'k1160',  // k92, g2794,
    // from: '广州',
    // to: '郑州',
    // fromCode: 'GZQ',
    // toCode: 'ZZF',
    // choose_seats: '', // 1D1F  如果二人优先选择， 如果三人 1A1B1C
    messageConfig: {
        appid: 'otn',
    },
}

var stop = false

var sessionTaskId

utils = {


    getTrain: function (trainNo, tickets) {
        trainNo = trainNo.toUpperCase()
        return tickets.filter(e=>e.trainNo === trainNo)[0]
    },

    // str 格式： 20240110, 返回格式 yyyy-mm-dd
    getDate: function(str) {
        const d = new Date(
            parseInt(str.substring(0, 4)),   // 年
            parseInt(str.substring(4, 6)) - 1, // 月 (注意月份是从0开始的，所以需要减去1)
            parseInt(str.substring(6, 8))      // 日
        )
        return `${d.getFullYear()}-${('0' + (d.getMonth() + 1)).slice(-2)}-${('0' + d.getDate()).slice(-2)}`;
    },

    getCurrentTime: function() {
        // 创建一个 Date 对象，它将包含当前的日期和时间
        const currentDate = new Date();

        // 获取当前时间的小时、分钟和秒
        const hours = currentDate.getHours();
        const minutes = currentDate.getMinutes();
        const seconds = currentDate.getSeconds();

        // 打印当前时间
        return `Time: ${hours}:${('0'+minutes).slice(-2)}:${('0'+seconds).slice(-2)} - `;
    },

     sleep: async function(s) {
        return await new Promise((resolve, reject)=>{
            // console.log(`${getCurrentTime()} 等待：${s} s`)
            setTimeout(()=> {
                resolve(true)
            }, s * 1000)
        })
    },

    log: function(...params) {
        console.log(`${this.getCurrentTime()}`, ...params)
    },

    outToPlain: function (text) {
        const old = $("#ticketLogTextarea").val()

        const newText = `${this.getCurrentTime()} - ${text} \n${old}`

        $("#ticketLogTextarea").val(newText);
    },

    toDay: function () {
        const d = new Date()
        return `${d.getFullYear()}-${('0' + (d.getMonth() + 1)).slice(-2)}-${('0' + (d.getDate() + 1)).slice(-2)}`
    },

    price: function (code) {

        const b5 = function (c9) {
            if (c9 === "0") {
                return ""
            }
            var c8 = c9.toString().indexOf(".") === -1 ? c9 + ".0" : c9;
            return "&yen;" + c8
        }

        const prices = {};
        const count = code.length / 10;
        for (let i = 0; i < count; i++) {
            var db = code.substring(i * 10, i * 10 + 10);
            var c8 = db.substring(0, 1);
            var da = db.substring(6, 7);
            var df = b5(Number(db.substring(1, 6)) / 10);
            if ("3" === da) {
                prices.W = df
            } else {
                prices[c8] = df
            }
        }
        return prices
    },

    getPassengerTickets: function(seatType, passengers) {
        let aA = "";
        for (var aB = 0; aB < passengers.length; aB++) {
            var aC = seatType + ",0," + 1 + "," + passengers[aB].passenger_name + "," + 1 + "," + passengers[aB].passenger_id_no + "," + (passengers[aB].mobile_no == null ? "" : passengers[aB].mobile_no) + "," + 'N' + "," + passengers[aB].allEncStr;
            aA += aC + "_"
        }
        return aA.substring(0, aA.length - 1)
    },

    getOldPassengers: function(passengers) {
        let aE = "";
        for (let aD = 0; aD < passengers.length; aD++) {
            let aA = passengers[aD];
            // if (passengers.tour_flag == ticket_submit_order.tour_flag.fc || ticketInfoForPassengerForm.tour_flag == ticket_submit_order.tour_flag.gc) {
            let aB = aA.passenger_name + "," + '1' + "," + aA.passenger_id_no + "," + '1';
            aE += aB + "_"
            // }
            // else {
            //     if (aA.only_id.indexOf("djPassenger_") > -1) {
            //         var aC = aA.only_id.split("_")[1];
            //         var aB = M[aC].passenger_name + "," + M[aC].passenger_id_type_code + "," + M[aC].passenger_id_no + "," + M[aC].passenger_type;
            //         aE += aB + "_"
            //     } else {
            //         if (aA.only_id.indexOf("normalPassenger_") > -1) {
            //             var aC = aA.only_id.split("_")[1];
            //             var aB = az[aC].passenger_name + "," + az[aC].passenger_id_type_code + "," + az[aC].passenger_id_no + "," + az[aC].passenger_type;
            //             aE += aB + "_"
            //         } else {
            //             aE += "_ "
            //         }
            //     }
            // }
        }
        return aE
    },


    stopTask: function() {
        stop = true
        $('#tab1 #startTask').prop('disabled', false)
        utils.outToPlain(`停止任务`)
        this.closeSession()
    },

    // 保持会话可用
    activeSession: function() {
        this.log('开启保持会话')
        sessionTaskId = setInterval(()=>{
            this.outToPlain('正在抢票，请等待......')
            fetch('https://kyfw.12306.cn/otn/index/initMy12306Api', {method: 'get'}).then(resp=>{
                try {
                    return resp.json()
                } catch (e) {
                }
                return {}
            }).then(data=>{
                utils.log('activeSession', data)
            }).catch(e=>{

            })
        }, 60 * 1000)
    },

    closeSession: function() {
        clearInterval(sessionTaskId)
    },

    autoOrder: async function (config) {
        for(;;) {
            if(stop) {
                this.log('退出查询。')
                return
            }
            try{
                const tickets = await ticketApi.leftTicketQuery(config.fromCode, config.toCode, config.data)
                if (tickets.length === 0) {
                    // this.outToPlain(`查不到班车: ${config.data} ${config.trainNo} ${config.from} --> ${config.to}`)
                    await this.sleep(globalConfig.waitTime)
                    continue
                }
                const ticket = utils.getTrain(config.trainNo, tickets)
                // 判断是否开卖
                if(ticket.isSell !== 'Y') {
                    await this.sleep(globalConfig.waitTime)
                    continue
                }

                const seats = config.seats
                for (let i = 0; i < seats.length; i++) {
                    if(seats[i] === 'O' && ticket.secondClass && ticket.secondClass !== '无') {
                        config.seat = 'O'
                        if(ticket.secondClass !== '有') {
                            const t = parseInt(ticket.secondClass) || 0
                            if(t < config.selectPassengers.length) {
                                config.seat = ''
                            }
                        }
                    } else if(seats[i] === 'M' && ticket.firstClass && ticket.firstClass !== '无'){
                        config.seat = 'M'
                        if(ticket.firstClass !== '有') {
                            const t = parseInt(ticket.firstClass) || 0
                            if(t < config.selectPassengers.length) {
                                config.seat = ''
                            }
                        }
                    } else if(seats[i] === '4' && ticket.softSleeper && ticket.softSleeper !== '无'){
                        config.seat = '4'
                        if(ticket.softSleeper !== '有') {
                            const t = parseInt(ticket.softSleeper) || 0
                            if(t < config.selectPassengers.length) {
                                config.seat = ''
                            }
                        }
                    } else if(seats[i] === '3' && ticket.hardSleeper && ticket.hardSleeper !== '无'){
                        config.seat = '3'
                        if(ticket.hardSleeper !== '有') {
                            const t = parseInt(ticket.hardSleeper) || 0
                            if(t < config.selectPassengers.length) {
                                config.seat = ''
                            }
                        }
                    } else if(seats[i] === '1' && ticket.hardClass && ticket.hardClass !== '无'){
                        config.seat = '1'
                        if(ticket.hardClass !== '有') {
                            const t = parseInt(ticket.hardClass) || 0
                            if(t < config.selectPassengers.length) {
                                config.seat = ''
                            }
                        }
                    } else {
                        config.seat = ''
                    }
                    if(config.seat !== '') {
                        break
                    }
                }

                if(config.seat !== '' && ! globalConfig.submitFailed) {
                    this.outToPlain(`${ticket.trainNo}, 日期：${ticket.date}, 二等座：${ticket.secondClass || "无"}, 软卧：${ticket.softSleeper || "无"}, 硬卧：${ticket.hardSleeper  || "无"}` )

                    await ticketApi.submitOrderRequest(ticket, config)

                    // 提交的订单信息
                    this.outToPlain(`queryOrderWaitTime =>  提交订单`)
                    const orderInfo = await ticketApi.confirmPassenger()
                    // 检查票数
                    this.outToPlain(`checkOrderInfo =>  检查票数`)
                    const checkOrder = await ticketApi.checkOrderInfo(config)

                    if(checkOrder.data.errMsg) {
                        this.outToPlain(checkOrder.data.errMsg)
                        await this.sleep(globalConfig.waitTime)
                        continue
                    }

                    // 获取剩余票数
                    const ticketInfo = await ticketApi.getQueueCount(ticket, config)
                    if(ticketInfo.data.ticket  === '0') {
                        this.outToPlain('余票不足：总数为： ' + ticketInfo.data.ticket)
                        this.outToPlain('等待 10 秒 ：')
                        await sleep(10)
                        continue
                    }

                    // 预下单
                    this.outToPlain(`checkOrderInfo =>  预下单, 锁定车票`)
                    await ticketApi.confirmSingleForQueue(orderInfo, config)

                    await ticketApi.orderStatus()

                    let orderSuccessInfo =  await ticketApi.queryOrderWaitTime()
                    while(! orderSuccessInfo.data.orderId) {
                        this.log(`queryOrderWaitTime => 等待出票结果。。。${JSON.stringify(orderSuccessInfo.data)}`)
                        this.outToPlain(`queryOrderWaitTime => 等待出票结果。。。`)
                        await this.sleep(1)
                        orderSuccessInfo =  await ticketApi.queryOrderWaitTime()

                        if(orderSuccessInfo.data.msg) {
                            if(orderSuccessInfo.data.msg === '很抱歉！当前提交订单用户过多，请您稍候重试。') {
                                this.outToPlain('很抱歉！当前提交订单用户过多，请您稍候重试。')
                                break
                            } else if(orderSuccessInfo.data.msg === '对不起，由于您取消次数过多，今日将不能继续受理您的订票请求。明日您可继续使用订票功能。') {
                                this.outToPlain('对不起，由于您取消次数过多，今日将不能继续受理您的订票请求。明日您可继续使用订票功能。')
                                this.stopTask()
                                break
                            } else if(orderSuccessInfo.data.msg === '没有足够的票!') {
                                this.outToPlain(orderSuccessInfo.data.msg)
                                break
                            } else {
                                this.log('queryOrderWaitTime => 未知的信息：' + orderSuccessInfo.data.msg)
                                break
                            }

                        }
                    }

                    if(orderSuccessInfo.data.orderId) {
                        const payInfo = await ticketApi.resultOrderForDcQueue(orderSuccessInfo)
                        this.log(`resultOrderForDcQueue => ${JSON.stringify(payInfo)}`)
                        this.outToPlain('抢票成功')
                        this.stopTask()
                        await ticketApi.sendCode() // 发送短信
                        this.outToPlain('发送短信...')
                        // alert(`软卧：${ticket.softSleeper || "无"}, 硬卧：${ticket.hardSleeper  || "无"}`)
                        return
                    } else {
                        // 订单没有提交成功。等待一会儿，否则会被封 ip
                        globalConfig.submitFailed = true
                        utils.log('出票失败，停止一会儿，等待下次一的提交。。')
                        this.outToPlain('出票失败，停止一会儿，等待下次一的提交。')
                        setTimeout(()=> {
                            utils.log('出票失败，等待结束。。')
                            this.outToPlain('出票失败，等待结束。')
                            globalConfig.submitFailed = false
                        }, globalConfig.submitWaitTime * 1000)
                    }
                }

                await this.sleep(globalConfig.waitTime)
            } catch (e) {
                console.log(e)
                break
            }

        }
    },

     startTask: function(config) {
        this.activeSession()
        this.autoOrder(config)
    }
}

ticketApi = {

    loginInfo: function(call) {

        fetch('https://kyfw.12306.cn/otn/index/initMy12306Api', {method: 'get'})
            .then(resp=> {
                return resp.json()
            })
            .then(data=> {
                call(data)
            }).catch(e=>{

        })

    },

    userInfo: function (call) {
        // https://kyfw.12306.cn/otn/login/conf
        fetch('https://kyfw.12306.cn/otn/login/conf', {method: 'post', })
            .then(resp=> {
                return resp.json()
            })
            .then(data=> {
                call(data)
            })
    },

    leftTicketQuery: async function (from, to, date) {
        const timeout = globalConfig.timeout; // Set the timeout in milliseconds (e.g., 5 seconds)
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), timeout);
        try{

            const data = await (await fetch(`${TICKET_URL}?leftTicketDTO.train_date=${date}&leftTicketDTO.from_station=${from}&leftTicketDTO.to_station=${to}&purpose_codes=ADULT`
                , {signal: controller.signal}))
                .json()
            let result = data.data.result
            result = result.map(e=>{
                const d = e.split('|')
                return {
                    sellTime: d[1],
                    trainNumber: d[2],
                    trainNo: d[3], departure: d[4], terminal: d[5], getOnstation: d[6], passingBy: d[7],
                    leftTicket: d[12],
                    date: d[13],
                    isSell: d[11],
                    softSleeper: d[23],
                    noneClass: d[26],
                    hardSleeper: d[28],
                    hardClass: d[29],
                    secondClass: d[30],
                    firstClass: d[30],
                    startTime: d[8],
                    endTime: d[9],
                    time: d[10],
                    token: d[0],
                    bedLevelInfo: d[53],
                    seatDiscountInfo: d[54],
                    priceText: d[39],
                }
            })
            return result
        }catch (error) {
            if (error.name === 'AbortError') {
                console.warn('Request timed out', error.message);
            } else {
                console.warn('Error fetching data:', error.message);
            }
            return []
        } finally {
            clearTimeout(timeoutId);
        }

    },

    queryTickets: async function(from, to, date) {
        const timeout = globalConfig.timeout; // Set the timeout in milliseconds (e.g., 5 seconds)
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), timeout);
        try{

            const data = await (await fetch(`${TICKET_URL}?leftTicketDTO.train_date=${date}&leftTicketDTO.from_station=${from}&leftTicketDTO.to_station=${to}&purpose_codes=ADULT`
                , {signal: controller.signal}))
                .json()
            let result = data.data.result
            result = result.map(e=>{
                const d = e.split('|')
                return {
                    sellTime: d[1],
                    trainNumber: d[2],
                    trainNo: d[3], departure: d[4], terminal: d[5], getOnstation: d[6], passingBy: d[7],
                    leftTicket: d[12],
                    date: d[13],
                    isSell: d[11],
                    softSleeper: d[23],
                    noneClass: d[26],
                    hardSleeper: d[28],
                    hardClass: d[29],
                    secondClass: d[30],
                    firstClass: d[30],
                    startTime: d[8],
                    endTime: d[9],
                    time: d[10],
                    token: d[0],
                    bedLevelInfo: d[53],
                    seatDiscountInfo: d[54],
                    priceText: d[39],
                }
            })
            data.data.result = result
            return data.data
        }catch (error) {
            if (error.name === 'AbortError') {
                console.warn('Request timed out', error.message);
            } else {
                console.warn('Error fetching data:', error.message);
            }
            return []
        } finally {
            clearTimeout(timeoutId);
        }
    },

    queryByTrainNo: async function (date, trainNo, fromCode, toCode) {
        const u = `https://kyfw.12306.cn/otn/czxx/queryByTrainNo?train_no=${trainNo}&from_station_telecode=${fromCode}&to_station_telecode=${toCode}&depart_date=${date}`
        try{
            const data = await (await fetch(u)).json()
            return  data.data.data
        }catch (e) {
            utils.log(e)
            return []
        }
    },

    // 乘客信息。
    getPassenger: async function () {
        const p = {
            _json_att: '',
            'REPEAT_SUBMIT_TOKEN': '',
        }
        const params = new URLSearchParams();
        for (const key in p) {
            params.append(key, p[key]);
        }
//
        // https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs
        const data = await (await fetch('https://kyfw.12306.cn/otn/passengers/query?pageIndex=1&pageSize=10', {
            method: 'post',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
            },
            body: params,
        }))
            .json()
        return data.data.datas
    },

    // 如果抢票成功了就发送登录的短信提示，在12306手机APP付款，
    sendCode: async function () {
        const p = globalConfig.messageConfig
        if(! p.username || ! p.castNum) {
            return
        }

        const params = new URLSearchParams();
        for (const key in p) {
            params.append(key, p[key]);
        }
        const data = await (await fetch('https://kyfw.12306.cn/passport/web/getMessageCode',
            {
                method:'post',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                },
                body: params,
            })).json()

        utils.log(data)
    },

    submitOrderRequest: async function (ticket, config) {
        const p = {
            secretStr: decodeURIComponent(ticket.token),
            train_date: utils.getDate(ticket.date),
            back_train_date: utils.getDate(ticket.date),
            tour_flag: 'dc',
            purpose_codes: 'ADULT',
            query_from_station_name: config.from,
            query_to_station_name: config.to,
            bed_level_info: ticket.bedLevelInfo || '',
            seat_discount_info: ticket.seatDiscountInfo || '',
            'undefined': '',
        }
        const params = new URLSearchParams();
        for (const key in p) {
            params.append(key, p[key]);
        }

        const data = await (await fetch('https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest', {
            method: 'post',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
            },
            body: params,
        }))
            .json()
        console.log(JSON.stringify(data, null, 4))
        return data
    },

    // 获取提交的订单信息。
    confirmPassenger: async function () {
        const data = await (await fetch('https://kyfw.12306.cn/otn/confirmPassenger/initDc', {method: 'post'})).text()

        const orderInfo = JSON.parse(data.split('\n').filter(e=>e.indexOf('var ticketInfoForPassengerForm') > -1)[0]
            .split('=')[1].replace(';', '').replaceAll("'", '"'))

        orderInfo.reToken = data.split('\n').filter(e=>e.trim().indexOf('var globalRepeatSubmitToken') > -1)[0]
            .split('=')[1].replace(';', '').replaceAll('\'', '')

        return orderInfo
    },

    /*
    有票
    {
        "validateMessagesShowId": "_validatorMessage",
        "status": true,
        "httpstatus": 200,
        "data": {
            "canChooseBeds": "N",
            "canChooseSeats": "Y",
            "choose_Seats": "MO",
            "isCanChooseMid": "N",
            "ifShowPassCodeTime": "3712",
            "submitStatus": true,
            "smokeStr": ""
        },
        "messages": [],
        "validateMessages": {}
    }

    错误消息
     {
        "validateMessagesShowId": "_validatorMessage",
        "status": true,
        "httpstatus": 200,
        "data": {
            "checkSeatNum": true,
            "errMsg": "您选择了1位乘车人，但本次列车null仅剩0张。",
            "submitStatus": false
        },
        "messages": [],
        "validateMessages": {}
    }
     */
    checkOrderInfo: async function (config) {

        const passengers = config.selectPassengers.map(e=> globalConfig.passengers[e])

        const p = {
            'cancel_flag': 2,
            'bed_level_order_num': '000000000000000000000000000000',
            'passengerTicketStr': utils.getPassengerTickets(config.seat, passengers),
            'oldPassengerStr': utils.getOldPassengers(passengers),
            'tour_flag': 'dc',
            'whatsSelect': 1,
            'sessionId': '',
            'sig': '',
            'scene': 'nc_login',
            '_json_att': '',
            'REPEAT_SUBMIT_TOKEN': ''
        }
        const params = new URLSearchParams();
        for (const key in p) {
            params.append(key, p[key]);
        }

        const data = await (await fetch('https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo', {
            method: 'post',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            },
            body: params,
        }))
            .json()
        console.log(JSON.stringify(data, null, 4))
        return data
    },

    /*
    {
        "validateMessagesShowId": "_validatorMessage",
        "status": true,
        "httpstatus": 200,
        "data": {
            "count": "0",
            "ticket": "5",
            "op_2": "false",
            "countT": "0",
            "op_1": "false"
        },
        "messages": [],
        "validateMessages": {}
    }
     */
    getQueueCount: async function (tickerInfo, config) {
        const p = {
            'train_date': `${new Date(config.data).toString().split(' ', 4).join(' ')} 00:00:00 GMT+0800 (中国标准时间)`,
            'train_no': tickerInfo.trainNumber,
            'stationTrainCode': tickerInfo.trainNo,
            'seatType': config.seat,
            'fromStationTelecode': tickerInfo.getOnstation,
            'toStationTelecode': tickerInfo.passingBy,
            'leftTicket': tickerInfo.leftTicket,
            'purpose_codes': '00',
            'train_location': 'Q9',
            '_json_att': '',
            'REPEAT_SUBMIT_TOKEN': '',
        }
        const params = new URLSearchParams();
        for (const key in p) {
            params.append(key, p[key]);
        }

        const data = await (await fetch('https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount', {
            method: 'post',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            },
            body: params,
        }))
            .json()
        console.log(JSON.stringify(data, null, 4))

        return data
    },

    /*
     {
        "repeatSubmitToken": "0abf1f9898f761aa2299ea83f4fee07e",
        "validateMessagesShowId": "_validatorMessage",
        "status": true,
        "httpstatus": 200,
        "data": {
            "errMsg": "您的请求已在处理中，请在未完成订单中查询订单状态！",
            "submitStatus": false
        },
        "messages": [],
        "validateMessages": {}
    }
    {
    "validateMessagesShowId": "_validatorMessage",
    "status": true,
    "httpstatus": 200,
    "data": {
        "errMsg": "余票不足！",
        "submitStatus": false
    },
    "messages": [],
    "validateMessages": {}
}
     */
    confirmSingleForQueue: async function (orderInfo, config) {

        const passengers = config.selectPassengers.map(e=> globalConfig.passengers[e])

        const p = {
            passengerTicketStr: utils.getPassengerTickets(config.seat, passengers),
            oldPassengerStr: utils.getOldPassengers(passengers),
            purpose_codes: orderInfo.purpose_codes,
            key_check_isChange: orderInfo.key_check_isChange,
            leftTicketStr: orderInfo.leftTicketStr,
            train_location: orderInfo.train_location,
            choose_seats: '',
            seatDetailType: '000',
            is_jy: 'N',
            is_cj: 'Y',
            encryptedData: '',//tokenGenerate(),
            whatsSelect: 1,
            roomType: '00',
            dwAll: 'N',
            _json_att: '',
            REPEAT_SUBMIT_TOKEN: orderInfo.reToken,
        }
        const params = new URLSearchParams();
        for (const key in p) {
            params.append(key, p[key]);
        }

        const data = await (await fetch('https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue', {
            method: 'post',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            },
            body: params,
        })).json()

        utils.log('confirmSingleForQueue => ', JSON.stringify(data, null, 4))
        return data
    },

    /*
    {
        "validateMessagesShowId": "_validatorMessage",
        "status": true,
        "httpstatus": 200,
        "data": true,
        "messages": [],
        "validateMessages": {}
    }
     */
    orderStatus: async function () {
        const data = await (await fetch('https://kyfw.12306.cn/otn/basedata/log', {method:'post'})).json()

        utils.log('orderStatus => ', data)
    },

    /*
    查询抢票结果
    1. 等待处理结果
    {
        "validateMessagesShowId": "_validatorMessage",
        "status": true,
        "httpstatus": 200,
        "data": {
            "queryOrderWaitTimeStatus": true,
            "count": 0,
            "waitTime": -100,
            "requestId": 7150860083437881729,
            "waitCount": 0,
            "tourFlag": "dc",
            "orderId": null
        },
        "messages": [],
        "validateMessages": {}
    }
    2. 出票完成生成订单id，orderId: EC49260914
    {
        "validateMessagesShowId": "_validatorMessage",
        "status": true,
        "httpstatus": 200,
        "data": {
            "queryOrderWaitTimeStatus": true,
            "count": 0,
            "waitTime": -1,
            "requestId": 7151131680061114753,
            "waitCount": 0,
            "tourFlag": "dc",
            "orderId": "EC49260914"
        },
        "messages": [],
        "validateMessages": {}
    }
    3. 其余出票失败
    {
        "validateMessagesShowId": "_validatorMessage",
        "status": true,
        "httpstatus": 200,
        "data": {
            "queryOrderWaitTimeStatus": true,
            "count": 0,
            "waitTime": -2,
            "requestId": 7150857528498571649,
            "waitCount": 0,
            "tourFlag": "dc",
            "errorcode": "-1",
            "msg": "很抱歉！当前提交订单用户过多，请您稍候重试。",
            "orderId": null
        },
        "messages": [],
        "validateMessages": {}
    }

    {
        "validateMessagesShowId": "_validatorMessage",
        "status": true,
        "httpstatus": 200,
        "data": {
            "queryOrderWaitTimeStatus": true,
            "count": 0,
            "waitTime": -2,
            "requestId": 7150858935150692737,
            "waitCount": 0,
            "tourFlag": "dc",
            "errorcode": "",
            "msg": "对不起，由于您取消次数过多，今日将不能继续受理您的订票请求。明日您可继续使用订票功能。",
            "orderId": null
        },
        "messages": [],
        "validateMessages": {}
    }

    */
    queryOrderWaitTime: async function () {
        try {
            const data = await (await fetch('https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime?random=&tourFlag=dc&_json_att=&REPEAT_SUBMIT_TOKEN=', {method:'post'})).json()
            utils.log(data)
            return data
        } catch (e) {
            utils.outToPlain('网络出错, 继续等待...')
            return {
                data: {

                }
            }
        }
    },

    /*

    查询支付状态
    1. 成功信息
    {
        "validateMessagesShowId": "_validatorMessage",
        "status": true,
        "httpstatus": 200,
        "data": {
            "submitStatus": true
        },
        "messages": [],
        "validateMessages": {}
    }
    2. 处理失败
    {
        "validateMessagesShowId": "_validatorMessage",
        "status": true,
        "httpstatus": 200,
        "data": {
            "errMsg": "系统繁忙，请稍后重试！",
            "submitStatus": false
        },
        "messages": [],
        "validateMessages": {}
    }

    {
        "validateMessagesShowId": "_validatorMessage",
        "status": true,
        "httpstatus": 200,
        "data": {
            "errMsg": "获取订单信息失败，请查看未完成订单，继续支付！",
            "submitStatus": false
        },
        "messages": [],
        "validateMessages": {}
    }
     */
    resultOrderForDcQueue: async function (orderSequenceNo) {

        const p = {
            orderSequence_no: orderSequenceNo.data.orderId,
            _json_att: '',
            REPEAT_SUBMIT_TOKEN: '',
        }
        const params = new URLSearchParams();
        for (const key in p) {
            params.append(key, p[key]);
        }
        const data = await (await fetch('https://kyfw.12306.cn/otn/confirmPassenger/resultOrderForDcQueue',
            {
                method:'post',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                },
                body: params,
            })).json()

        utils.log(data)
        return data
    },
}

/*

C:\Users\80651>nslookup www.12306.cn
服务器:  dns.google
Address:  8.8.8.8

非权威应答:
名称:    www.12306.cn.lxdns.com
Addresses:  240e:97d:201c:201::36
          240e:97d:2014:a40::25
          183.6.211.61
          59.37.89.174
Aliases:  www.12306.cn


C:\Users\80651>nslookup kyfw.12306.cn
服务器:  dns.google
Address:  8.8.8.8

非权威应答:
名称:    kyfw.12306.cn.lxdns.com
Addresses:  240e:964:ea00:480::68
          240e:d6:660e:3::5f
          240e:964:ea00:80::4c
          240e:d6:660e:3::60
          117.27.251.194
          27.152.189.232
          125.77.136.14
          117.24.10.65
          117.27.251.195
Aliases:  kyfw.12306.cn



在中国地区，由于互联网管制和网络环境的特殊性，有一些常用的DNS服务器供用户选择。以下是一些常见的DNS服务器，它们可能有助于改善访问速度和稳定性：

114DNS:
IPv4：114.114.114.114、114.114.115.115
IPv6：2400:da00::6666、2400:da00::6666:8888

阿里DNS:
IPv4：223.5.5.5、223.6.6.6
IPv6：2400:3200::1、2400:3200:baba::1

腾讯DNS:
IPv4：119.29.29.29、182.254.118.118
IPv6：240e:180:ffff::1、240e:180:ffff::2

百度DNS:
IPv4：180.76.76.76
IPv6：2400:da00::6666:76

CNNIC DNS:
IPv4：1.2.4.8、210.2.4.8
IPv6：2402:f000:1:414:2001::2
 */


// var tickets = await leftTicketQuery('BJQ', 'HFH', '2024-01-24')
// 深圳东 'BJQ',  合肥 'HFH'
// await submitOrderRequest(getTrain('g636', tickets))

// 提交的订单信息
// var orderInfo = await confirmPassenger()

// 查询乘客
// var userInfoList = await getPassenger('')

// 检查票数
// await checkOrderInfo('')

// 获取剩余票数
// await getQueueCount(getTrain('g636', tickets))

// 预下单
// await confirmSingleForQueue(orderInfo)

// await orderStatus()

// await queryOrderWaitTime()

// await resultOrderForDcQueue()
//



